#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <functional>
#include "log.hpp"

// 我们要把tcp服务器设计为一个对象

// 默认端口
static const uint16_t default_port = 11111;
// 默认ip
static const std::string default_ip = "127.0.0.1";

namespace zxf
{
    class Tcp_client
    {
    public:
        Tcp_client(const std::string ip = default_ip, const int16_t port = default_port) // 构造函数
            : _ip(ip), _port(port), _listensock(-1)
        {
        }
        // 服务器初始化
        void initServer()
        {
            // std::cout<<"Tcp_server::initServer"<<std::endl;

            // 首先创建sock (socket)
            // 函数原型
            //        #include <sys/types.h>
            //        #include <sys/socket.h>
            //        int socket(int domain, int type, int protocol);
            // domain: 协议家族
            // type: 指定socket类型
            // protocol: 指定协议 ,为 0 会自动选择协议

            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock == -1)
            {
                std::cout << "socket error , exit" << std::endl;
                exit(SOCKET_ERR);
            }
            std::cout << "socket success!! " << std::endl;
        }

        // 开始运行服务器
        void start()
        {
            struct sockaddr_in net;
            socklen_t len = sizeof(net);
            bzero(&net, len);
            net.sin_family = AF_INET;
            net.sin_port = htons(_port);
            net.sin_addr.s_addr = inet_addr(_ip.c_str());
            // 发起链接
            //  #include <sys/types.h>
            //  #include <sys/socket.h>
            //  int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
            // 如果连接或绑定成功，则返回零。出现错误时，返回-1，并适当设置errno。
            int ret = connect(_listensock, (const sockaddr *)&net, len);
            if (ret < 0)
            {
                std::cout << "connect error , exit !! " << std::endl;
                exit(CONNECT_ERR);
            }
            std::cout << "connect success!! " << std::endl;

            for (;;)
            {
                // 处理信息
                std::string str;
                // istream& getline (istream& is, string& str);
                std::cout << "Entry#";
                std::getline(std::cin, str);
                if(str.size() == 0 )
                {
                    continue;
                }
                std::cout<<str<<std::endl;
                int ret = write(_listensock, str.c_str(), str.length());
                if (ret == -1)
                {
                    std::cout << "write error , exit" << std::endl;
                    exit(WRITE_ERR);
                }

                char buf[1024] = {0};
                bzero(buf, len);//初始化
                size_t len = sizeof(buf);
                ssize_t t = read(_listensock, buf, len);
                
                if (t < 0)
                {
                    //std::cout << "read error , exit" << std::endl;
                    exit(READ_ERR);
                }
                else if (t == 0)
                {
                    std::cout << "断开链接 " << std::endl;
                    // 关闭文件描述符(link_sock)
                    close(_listensock);
                    break; // 函数退出
                }
                else
                {
                    // 处理收到的信息
                    std::cout << buf << std::endl;
                }
            }
        }

    private:
        std::string _ip; // 远端服务器 IP
        int16_t _port;   // 远端服务器 port
        int _listensock;
    };

} // namespace zxf  end!!